home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs1.zip / MAIL / alias.c < prev    next >
C/C++ Source or Header  |  1993-07-20  |  17KB  |  446 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    a l i a s . c                                                   */
  3. /*                                                                    */
  4. /*    Smart routing and alias routines for UUPC/extend mail           */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) 1989-1993 by Kendra Electronic            */
  9. /*    Wonderworks.                                                    */
  10. /*                                                                    */
  11. /*    All rights reserved except those explicitly granted by the      */
  12. /*    UUPC/extended license agreement.                                */
  13. /*                                                                    */
  14. /*    Additional code                                                 */
  15. /*       Copyright (c) Richard H. Lamb 1985, 1986, 1987               */
  16. /*       Changes Copyright (c) Stuart Lynne 1987                      */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*--------------------------------------------------------------------*/
  20. /*                          RCS Information                           */
  21. /*--------------------------------------------------------------------*/
  22.  
  23. /*
  24.  *    $Id: alias.c 1.6 1993/07/21 01:19:16 ahd Exp $
  25.  *
  26.  *    Revision history:
  27.  *    $Log: alias.c $
  28.  * Revision 1.6  1993/07/21  01:19:16  ahd
  29.  * Incr elements after filling info from passwd, not before!
  30.  *
  31.  * Revision 1.5  1993/07/19  02:52:11  ahd
  32.  * Don't load alias for empty names
  33.  *
  34.  * Revision 1.4  1993/05/06  03:41:48  ahd
  35.  * Use expand_path to get reasonable correct drive for aliases file
  36.  *
  37.  * Revision 1.3  1993/04/11  00:33:05  ahd
  38.  * Global edits for year, TEXT, etc.
  39.  *
  40.  * Revision 1.2  1992/11/22  21:06:14  ahd
  41.  * Use strpool for memory allocation
  42.  *
  43.  *    02 Oct 89   Alter large strings/structures to use
  44.  *                malloc()/free()                              ahd
  45.  *    08 Feb 90   Correct failure of ExtractAddress to return
  46.  *                non-names                                    ahd
  47.  *    18 Mar 90   Move checkname() and associated routines into
  48.  *                hostable.c                                   ahd
  49.  *    22 Apr 90   Modify user_at_node to correctly handle .UUCP
  50.  *                alias on local host.                         ahd
  51.  *
  52.  */
  53.  
  54. #include <ctype.h>
  55. #include <stdio.h>
  56. #include <string.h>
  57. #include <stdlib.h>
  58. #include <sys/types.h>
  59.  
  60. #ifndef __TURBOC__
  61. #include <search.h>
  62. #endif
  63.  
  64. #include "lib.h"
  65. #include "hostable.h"
  66. #include "security.h"
  67. #include "usertabl.h"
  68. #include "hlib.h"
  69. #include "alias.h"
  70. #include "address.h"
  71. #include "expath.h"
  72.  
  73. static size_t AliasCount = 0;
  74.  
  75. static struct AliasTable *alias = NULL;
  76.  
  77. int nickcmp( const void *a, const void *b );
  78.  
  79. static size_t LoadAliases( void ) ;
  80.  
  81. currentfile();
  82.  
  83. /*--------------------------------------------------------------------*/
  84. /*    I n i t R o u t e r                                             */
  85. /*                                                                    */
  86. /*    Verify, initialize the global routing data                      */
  87. /*--------------------------------------------------------------------*/
  88.  
  89. boolean InitRouter()
  90. {
  91.    boolean success = TRUE;       /* Assume the input data is good       */
  92.    struct HostTable *Hptr;
  93.  
  94. /*--------------------------------------------------------------------*/
  95. /*          Verify that the user gave us a good name server           */
  96. /*--------------------------------------------------------------------*/
  97.  
  98.    Hptr = checkreal(E_mailserv);
  99.    if (Hptr == BADHOST)
  100.    {
  101.       printmsg(0,"mail server '%s' must be listed in SYSTEMS file",
  102.          E_mailserv);
  103.       success = FALSE;
  104.    }
  105.    else if (Hptr->hstatus == localhost)  /* local system?     */
  106.    {
  107.       printmsg(0,"'%s' is name of this host and cannot be mail server",
  108.             E_mailserv);
  109.       success = FALSE;
  110.    }
  111.  
  112. /*--------------------------------------------------------------------*/
  113. /*                          Return to caller                          */
  114. /*--------------------------------------------------------------------*/
  115.  
  116.    return success;
  117. } /* InitRouter */
  118.  
  119. /*--------------------------------------------------------------------*/
  120. /*    E x t r a c t N a m e                                           */
  121. /*                                                                    */
  122. /*    Returns full name of user, and returns address if name          */
  123. /*    is not available.                                               */
  124. /*--------------------------------------------------------------------*/
  125.  
  126. void ExtractName(char *result, char *column)
  127. {
  128.       static int recursion = 0;
  129.  
  130.       recursion++;
  131.  
  132.       printmsg((recursion > 2) ? 1:8,
  133.             "ExtractName: Getting name from '%s'",column);
  134.  
  135.       ExtractAddress(result, column, TRUE);  /* Get the full name    */
  136.       if (!strlen(result))       /* Did we get the name?             */
  137.       {                          /* No --> Get the e-mail address    */
  138.          char addr[MAXADDR];
  139.          char path[MAXADDR];
  140.          char node[MAXADDR];
  141.          char *fullname;
  142.  
  143.          ExtractAddress(addr,column, FALSE);
  144.          user_at_node(addr,path,node,result);
  145.                                  /* Reduce address to basics */
  146.          fullname = AliasByAddr(node,result);
  147.          if (fullname == NULL)
  148.          {
  149.             strcat(result,"@");
  150.             strcat(result,node);
  151.          }
  152.          else
  153.             strcpy(result,fullname);
  154.       }
  155.  
  156.       printmsg((recursion > 2) ? 1: 8,"ExtractName: name is '%s'",result);
  157.  
  158.       recursion--;
  159.  
  160.       return;
  161. }  /*ExtractName*/
  162.  
  163. /*--------------------------------------------------------------------*/
  164. /*    B u i l d A d d r e s s                                         */
  165. /*                                                                    */
  166. /*    Builds a standard address format, with aliasing as              */
  167. /*    required.                                                       */
  168. /*--------------------------------------------------------------------*/
  169.  
  170. void BuildAddress(char *result, const char *input)
  171. {
  172.    char addr[MAXADDR];
  173.    char name[MAXADDR];
  174.    char user[MAXADDR];
  175.    char path[MAXADDR];
  176.    char node[MAXADDR];
  177.    char *fulladdr;
  178.  
  179. /*--------------------------------------------------------------------*/
  180. /*   It must be a real address, possibly with a name attached; get    */
  181. /*   the address portion, break the address into user and node, and   */
  182. /*   then see if we know the person by address                        */
  183. /*--------------------------------------------------------------------*/
  184.  
  185.       ExtractAddress(addr,input,FALSE);   /* Get user e-mail addr    */
  186.       user_at_node(addr,path,node,user);  /* Break address down      */
  187.  
  188.       fulladdr = AliasByAddr(node,user);  /* Alias for the address?  */
  189.       if (fulladdr != NULL)            /* Yes --> Use it             */
  190.       {
  191.          strcpy(result,fulladdr);
  192.          return;
  193.       } /* if */
  194.  
  195. /*--------------------------------------------------------------------*/
  196. /*   We don't know the address yet; get the name the user provided,   */
  197. /*   and then normalize the address                                   */
  198. /*--------------------------------------------------------------------*/
  199.  
  200.       ExtractAddress(name,input,TRUE);    /* Also get their name     */
  201.  
  202.       if (strlen(name))             /* Did we find a name for user?  */
  203.       {                             /* Yes --> Return it             */
  204.          char *s = strchr(node, '.');
  205.          if ((s == NULL) || equalni( s, ".UUCP", 5))
  206.                                     /* Simple name or UUCP domain?   */
  207.          {                          /* Yes--> Use original address   */
  208.             size_t pathlen = strlen(path);/* Save len of orig path   */
  209.             if ((pathlen > strlen(addr)) &&
  210.                 (!equal(node,path)) && /* Target not a known host?   */
  211.                 equaln(addr,path, strlen(path)) && /* & host starts  */
  212.                 (addr[pathlen] == '!'))   /* ...the address?         */
  213.                fulladdr = &addr[pathlen + 1];   /* Yes --> Drop it   */
  214.             else
  215.                fulladdr = addr;  /* No --> Use full address          */
  216.             sprintf(result,"(%s) %s", name, addr);
  217.          } /* (strchr(node, '.') == NULL) */
  218.          else                    /* No --> Use RFC-822 format        */
  219.             sprintf(result,"\"%s\" <%s@%s>", name, user, node);
  220.       } /* if strlen(name) */
  221.       else
  222.          strcpy(result,addr);    /* No name, just use the original   */
  223. } /* BuildAddress */
  224.  
  225.  
  226. /*--------------------------------------------------------------------*/
  227. /*    A l i a s B y N i c k                                           */
  228. /*                                                                    */
  229. /*    Locate a mail address by search the alias table.  Returns TRUE  */
  230. /*    if alias found and has address, otherwise FALSE.                */
  231. /*--------------------------------------------------------------------*/
  232.  
  233. char *AliasByNick(const char *nick)
  234. {
  235.    int   upper;
  236.    int   lower;
  237.  
  238.    if (!AliasCount)
  239.       AliasCount = LoadAliases();
  240.  
  241.    upper = AliasCount - 1;
  242.    lower = 0;
  243.  
  244.    while (upper >= lower)
  245.    {
  246.       int midpoint;
  247.       int hit;
  248.  
  249.       midpoint = ( upper + lower ) / 2;
  250.       hit = stricmp(nick,alias[midpoint].anick);
  251.       if (!hit)
  252.          return alias[midpoint].afull;
  253.       if ( hit > 0 )
  254.          lower = midpoint + 1;
  255.       else
  256.          upper = midpoint - 1;
  257.    }
  258.    return NULL;
  259. }
  260.  
  261.  
  262. /*--------------------------------------------------------------------*/
  263. /*    A l i a s B y A d d r                                           */
  264. /*                                                                    */
  265. /*    Locate a mail address by search the alias table.  Returns TRUE  */
  266. /*    if alias found and has address, otherwise FALSE                 */
  267. /*--------------------------------------------------------------------*/
  268.  
  269. char *AliasByAddr(const char *node, const char *user)
  270. {
  271.    size_t current = 0;
  272.  
  273.    if (!AliasCount)
  274.       AliasCount = LoadAliases();
  275.  
  276.    while (current < AliasCount)
  277.    {
  278.       int hit;
  279.  
  280.       hit = stricmp(node,alias[current].anode);
  281.       if (!hit)
  282.       {
  283.          hit = stricmp(user,alias[current].auser);
  284.          if (!hit)
  285.             return alias[current].afull;
  286.       }
  287.       current++;
  288.    }
  289.    return NULL;
  290.  
  291. }
  292.  
  293.  
  294. /*--------------------------------------------------------------------*/
  295. /*    L o a d A l i a s e s                                           */
  296. /*                                                                    */
  297. /*    Initializes the address alias table; returns number of aliases  */
  298. /*    loaded                                                          */
  299. /*--------------------------------------------------------------------*/
  300.  
  301. size_t LoadAliases(void)
  302. {
  303.    FILE *ff;
  304.    char buf[BUFSIZ];
  305.    char *token;
  306.    size_t   elements = 0;
  307.    size_t   max_elements = UserElements + 20;
  308.    size_t   subscript;
  309.    struct AliasTable *hit;           /* temporary pointer for searching  */
  310.    struct AliasTable target;
  311.  
  312.  
  313.    checkuser( E_mailbox ); /* Force the table to be loaded           */
  314.    alias = calloc(max_elements, sizeof(*alias));
  315.    checkref(alias);
  316.  
  317. /*--------------------------------------------------------------------*/
  318. /*                   Actually load the alias table                    */
  319. /*--------------------------------------------------------------------*/
  320.  
  321.    if (E_aliases != NULL )    /* Did the user specify aliases file?  */
  322.    {
  323.       char fname[FILENAME_MAX];
  324.  
  325.       strcpy( fname, E_aliases);
  326.       expand_path( fname, E_homedir, E_homedir , NULL );
  327.       ff = FOPEN(fname , "r",TEXT_MODE);
  328.  
  329.       if (ff == NULL)
  330.       {
  331.          printerr(fname);
  332.          return elements;
  333.       } /* if */
  334.  
  335.       while (! feof(ff))
  336.       {
  337.          if (fgets(buf,BUFSIZ,ff) == NULL)   /* Try to read a line      */
  338.             break;                  /* Exit if end of file              */
  339.          token = strtok(buf," \t\n");
  340.          if (token == NULL)         /* Any data?                        */
  341.             continue;               /* No --> read another line         */
  342.          if (token[0] == '#')
  343.             continue;                  /* Line is a comment; loop again */
  344.  
  345.          /* Add the alias to the table.  Note that we must add the nick */
  346.          /* to the table ourselves (rather than use lsearch) because    */
  347.          /* we must make a copy of the string; the *token we use for    */
  348.          /* the search is in the middle of our I/O buffer!              */
  349.          /*
  350.          /* I was burned, _you_ have been warned.                       */
  351.  
  352.          target.anick = token;
  353.  
  354.          hit = (void *) lfind(&target, alias, &elements , sizeof(alias[0]),
  355.              nickcmp);
  356.          if (hit == NULL)
  357.          {
  358.             char node[MAXADDR];
  359.             char user[MAXADDR];
  360.             char path[MAXADDR];
  361.             char addr[MAXADDR];
  362.             char *eos;
  363.  
  364.             if (elements == max_elements)
  365.             {
  366.                 max_elements = max_elements * 2;
  367.                 alias = realloc(alias, max_elements * sizeof(*alias));
  368.                 checkref(alias);
  369.             }
  370.  
  371.             alias[elements].anick = newstr(token);
  372.             token = strtok(NULL,"");    /* Get rest of string         */
  373.  
  374.             while ( strlen(token) && isspace(*token))
  375.                token++;
  376.             eos = token + strlen(token) - 1;
  377.             while ( strlen(token) && isspace(*eos))
  378.             {
  379.                *eos = '\0';
  380.                eos--;
  381.             }
  382.  
  383.             alias[elements].afull = newstr(token);
  384.             ExtractAddress(addr,alias[elements].afull,FALSE);
  385.             user_at_node(addr,path,node,user);
  386.             alias[elements].anode = newstr(node);
  387.             alias[elements].auser = newstr(user);
  388.             elements += 1;
  389.          }
  390.          else
  391.             printmsg(0,"LoadAliases: Duplicate alias '%s' in table",token);
  392.       }
  393.       fclose(ff);
  394.    } /* if (E_aliases != NULL ) */
  395.  
  396. /*--------------------------------------------------------------------*/
  397. /*           Add the local users as final aliases in table            */
  398. /*--------------------------------------------------------------------*/
  399.  
  400.    alias = realloc(alias, (elements + UserElements) * sizeof(*alias));
  401.                               /* Resize table to final known size    */
  402.    checkref(alias);
  403.  
  404.    for ( subscript = 0; subscript < UserElements;  subscript++)
  405.    {
  406.       if ( equal(users[subscript].realname,EMPTY_GCOS) )
  407.          continue;
  408.  
  409.       alias[elements].anick = "";   /* No nickname, only good for addr  */
  410.       if (bflag[F_BANG])
  411.          sprintf(buf, "(%s) %s!%s",
  412.                users[subscript].realname, E_fdomain,
  413.                users[subscript].uid);
  414.       else
  415.          sprintf(buf, "\"%s\" <%s@%s>", users[subscript].realname,
  416.                users[subscript].uid, E_fdomain );
  417.       alias[elements].afull = newstr(buf);
  418.       alias[elements].anode = E_nodename;
  419.       alias[elements].auser = users[subscript].uid;
  420.  
  421.       elements++;
  422.    } /* for */
  423.  
  424. /*--------------------------------------------------------------------*/
  425. /*                         Now sort the table                         */
  426. /*--------------------------------------------------------------------*/
  427.  
  428.    qsort(alias, elements ,sizeof(alias[0]) , nickcmp);
  429.  
  430.    return (elements) ;
  431. } /*LoadAliases*/
  432.  
  433.  
  434. /*--------------------------------------------------------------------*/
  435. /*   n i c k c m p                                                    */
  436. /*                                                                    */
  437. /*   Accepts indirect pointers to two strings and compares them using */
  438. /*   stricmp (case insensitive string compare)                        */
  439. /*--------------------------------------------------------------------*/
  440.  
  441. int nickcmp( const void *a, const void *b )
  442. {
  443.    return stricmp(((struct AliasTable *)a)->anick,
  444.          ((struct AliasTable *)b)->anick);
  445. }  /*nickcmp*/
  446.